<template>
  <a-modal
    :open="visible"
    :title="isEdit ? '编辑文章' : '发布文章'"
    width="90%"
    :body-style="{ maxHeight: '70vh', overflow: 'auto' }"
    @cancel="handleCancel"
  >
    <template #footer>
      <a-button @click="handleCancel">取消</a-button>
      <a-button type="primary" :loading="submitting" @click="handleSubmit">
        {{ isEdit ? '保存' : '发布' }}
      </a-button>
    </template>

    <a-form
      ref="formRef"
      :model="formData"
      :rules="rules"
      :label-col="{ span: 3 }"
      :wrapper-col="{ span: 21 }"
    >
      <a-form-item label="文章标题" name="title">
        <a-input
          v-model:value="formData.title"
          placeholder="请输入文章标题"
          size="large"
          :maxlength="100"
          show-count
        />
      </a-form-item>

      <a-form-item label="文章封面" name="articleCover">
        <a-upload
          v-model:file-list="fileList"
          list-type="picture-card"
          class="cover-uploader"
          :before-upload="beforeUpload"
          :customRequest="handleUpload"
          :max-count="1"
          accept="image/*"
        >
          <div v-if="!formData.articleCover">
            <LoadingOutlined v-if="uploading" />
            <PlusOutlined v-else />
            <div style="margin-top: 8px">上传封面</div>
          </div>
        </a-upload>
        <div v-if="formData.articleCover" class="cover-preview-info">
          <a-typography-text type="secondary">
            图片路径：{{ baseUrl + formData.articleCover }}
          </a-typography-text>
        </div>
      </a-form-item>

      <a-form-item label="文章标签" name="categoryId">
        <a-select
          v-model:value="formData.categoryId"
          mode="tags"
          placeholder="请选择或输入标签"
          :options="categoryOptions"
          style="width: 100%"
        >
        </a-select>
        <div class="form-tip">支持选择或直接输入新标签，按回车添加</div>
      </a-form-item>

      <a-form-item label="文章内容" name="content" :wrapper-col="{ span: 24 }">
        <div class="markdown-editor-wrapper">
          <MdEditor
            v-model="formData.content"
            :preview="true"
            :toolbars="toolbars"
            :placeholder="'请输入文章内容，支持 Markdown 语法'"
            @onUploadImg="handleUploadImg"
          />
        </div>
      </a-form-item>
    </a-form>
  </a-modal>
</template>

<script setup lang="ts">
import { ref, reactive, watch, computed, onMounted } from 'vue'
import { message } from 'ant-design-vue'
import { PlusOutlined, LoadingOutlined } from '@ant-design/icons-vue'
import { MdEditor } from 'md-editor-v3'
import 'md-editor-v3/lib/style.css'
import type { UploadProps } from 'ant-design-vue'
import {
  getArticleTags,
  uploadImage,
  createArticle,
  updateArticle,
  getArticleDetail,
} from '@/api/article'
import { APP_CONFIG } from '@/config'

const baseUrl = APP_CONFIG.VITE_API_IMAGE_URL

interface Props {
  visible: boolean
  articleId?: number | null
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()
interface Emits {
  (e: 'update:visible', value: boolean): void
  (e: 'success'): void
}

// 监听props下的articleId变化
watch(
  () => props?.articleId,
  (val) => {
    if (val !== null) {
      // 编辑模式，获取文章详情
      getArticleDetail(val).then((res) => {
        if (res.code === 200) {
          // 编辑模式，填充数据
          formData.title = res.data.title
          formData.content = res.data.content
          formData.categoryId = res.data.categoryId.split(',')
          formData.articleCover = res.data.articleCover
        }
      })
    }
  }
)
const isEdit = computed(() => props.articleId !== null)
const formRef = ref()
const submitting = ref(false)
const uploading = ref(false)
const fileList = ref<any[]>([])

// 编辑器工具栏配置
const toolbars: any = [
  'bold',
  'underline',
  'italic',
  '-',
  'title',
  'strikeThrough',
  'sub',
  'sup',
  'quote',
  'unorderedList',
  'orderedList',
  'task',
  '-',
  'codeRow',
  'code',
  'link',
  'image',
  'table',
  '-',
  'revoke',
  'next',
  'save',
  '=',
  'pageFullscreen',
  'fullscreen',
  'preview',
  'htmlPreview',
  'catalog',
]

const formData = reactive({
  title: '',
  content: '',
  categoryId: [] as string[],
  articleCover: '',
})

const rules = {
  title: [{ required: true, message: '请输入文章标题', trigger: 'blur' }] as any,
  content: [{ required: true, message: '请输入文章内容', trigger: 'blur' }] as any,
  categoryId: [
    { required: true, message: '请选择文章标签', trigger: 'change', type: 'array' },
  ] as any,
}

// 标签选项（可以从后端获取）
const categoryOptions = ref([])
// 获取标签列表
const getCategoryOptions = async () => {
  const res = await getArticleTags()
  if (res.code === 200) {
    categoryOptions.value = res.data.map((item: any) => ({
      label: item.name,
      value: item.id.toString(),
    }))
  }
}

// 重置表单
const resetForm = () => {
  formData.title = ''
  formData.content = ''
  formData.categoryId = []
  formData.articleCover = ''
  fileList.value = []
  formRef.value?.clearValidate()
}

// 上传前校验
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
  const isImage = file.type.startsWith('image/')
  if (!isImage) {
    message.error('只能上传图片文件！')
    return false
  }
  const isLt5M = file.size / 1024 / 1024 < 5
  if (!isLt5M) {
    message.error('图片大小不能超过 5MB！')
    return false
  }
  return true
}

// 自定义上传封面
const handleUpload = async (options: any) => {
  const { file, onSuccess, onError } = options
  uploading.value = true

  try {
    const form = new FormData()
    form.append('file', file)
    const res = await uploadImage(form)
    console.log(res)

    if (res.code === 200) {
      formData.articleCover = res.data
      message.success('上传成功')
      onSuccess(baseUrl + res.data)
    }
  } catch (error) {
    onError(error)
    message.error('上传失败')
  } finally {
    uploading.value = false
  }
}

// Markdown 编辑器中上传图片
const handleUploadImg = async (files: File[], callback: (urls: string[]) => void) => {
  try {
    const uploadPromises = files.map(async (file) => {
      const formData = new FormData()
      formData.append('file', file)
      const res = await uploadImage(formData)
      return res.data.url
    })
    const imgUrls = await Promise.all(uploadPromises)
    console.log('编辑器上传的图片', imgUrls)
    // 模拟上传
    const urls = files.map((file) => URL.createObjectURL(file))
    callback(urls)
  } catch (error) {
    message.error('图片上传失败')
  }
}

// 取消
const handleCancel = () => {
  emit('update:visible', false)
  setTimeout(() => {
    resetForm()
  }, 300)
}

// 提交
const handleSubmit = async () => {
  try {
    await formRef.value.validate()
    submitting.value = true

    let res: any = null
    if (isEdit.value) {
      res = await updateArticle({
        ...formData,
        categoryId: formData.categoryId.join(','),
        id: props?.articleId,
      })
    } else {
      res = await createArticle({ ...formData, categoryId: formData.categoryId.join(',') })
    }

    if (res.code === 200) {
      message.success(isEdit.value ? '保存成功' : '发布成功')
      emit('success')
    } else {
      message.error(isEdit.value ? '保存失败' : '发布失败')
    }
  } catch (error: any) {
    if (error.errorFields) {
      message.error('请完善表单信息')
    } else {
      message.error(isEdit.value ? '保存失败' : '发布失败')
    }
  } finally {
    submitting.value = false
  }
}

onMounted(() => {
  getCategoryOptions()
})
</script>

<style scoped lang="less">
.cover-uploader :deep(.ant-upload) {
  width: 128px;
  height: 128px;
}

.cover-uploader :deep(.ant-upload-select-picture-card) {
  width: 128px;
  height: 128px;
}

.cover-preview-info {
  margin-top: 8px;
  font-size: 12px;
}

.form-tip {
  margin-top: 4px;
  color: #999;
  font-size: 12px;
}

.markdown-editor-wrapper {
  border: 1px solid #d9d9d9;
  border-radius: 4px;
  overflow: hidden;
}

.markdown-editor-wrapper :deep(.md-editor) {
  border: none;
}

:deep(.ant-form-item-label > label) {
  font-weight: 500;
}
:deep(.ant-upload) {
  width: 102px !important;
}
</style>
